package dev.touchswipe.shared.utils
{
	import flash.events.SampleDataEvent;
	import flash.utils.ByteArray;
	import flash.utils.Endian;

	public class WAVDecoder
	{
		public var AS3SoundData:ByteArray;
		private var RIFFchunkLength:uint;
		private var channels:uint;
		private var _stereo:Boolean;
		public function get stereo():Boolean
		{
			return _stereo;
		}

		private var _sampleRate:uint;
		public function get sampleRate():uint
		{
			return _sampleRate;
		}

		private var _bytesPerSecond:uint;
		public function get bytesPerSecond():uint
		{
			return _bytesPerSecond;
		}

		private var _blockAlign:uint;
		public function get blockAlign():uint
		{
			return _blockAlign;
		}

		public var _bitDepth:uint;
		public var _sampleDataLength:uint;
		
		public function WAVDecoder()
		{
			AS3SoundData=new ByteArray();
		}
		
		public function decode(data:ByteArray):void{
			data.endian=Endian.LITTLE_ENDIAN;
			if(data.readMultiByte(4,"us-ascii")!="RIFF"){
				throw new Error("Invalid WAV File: RIFF Header not found");
				return;
			}
			RIFFchunkLength=data.readUnsignedInt();
			if(data.readMultiByte(4,"us-ascii")!="WAVE"){
				throw new Error("Invalid WAV File: WAVE Header not found");
				return;
			}
			if(data.readMultiByte(4,"us-ascii")!="fmt "){
				throw new Error("Invalid WAV File: fmt Chunk not found");
				return;
			}
			if(data.readUnsignedInt()!=16||data.readShort()!=1){
				throw new Error("Invalid WAV File: Unsupported File");
				return;
			}
			channels=data.readUnsignedShort();
			switch (channels){
				case 1:
					_stereo=false;
					break;
				case 2:
					_stereo=true;
					break;
				default:
					throw new Error("Invalid WAV File: Bad number of Channels");
			}
			_sampleRate=data.readUnsignedInt();
			_bytesPerSecond=data.readUnsignedInt();
			_blockAlign=data.readShort();
			_bitDepth=data.readShort();
			if(data.readMultiByte(4,"us-ascii")!="data"){
				throw new Error("Invalid WAV File: data Chunk not found");
				return;
			}
			_sampleDataLength=data.readUnsignedInt();
			var s:uint=0;
			var leftSample:Number;
			var rightSample:Number;
			while(s<_sampleDataLength){
				if(_bitDepth==8){
					s++;
					leftSample=(data.readUnsignedByte()-128)/128;
					if(_stereo){
						rightSample=(data.readUnsignedByte()-128)/128;
						s++;
					}
					else
						rightSample=leftSample;
				}
				if(_bitDepth==16){
					leftSample=data.readShort()/32767;
					s+=2;
					if(_stereo){
						s+=2;
						rightSample=data.readShort()/32767;
					}
					else
						rightSample=leftSample;
				}
				AS3SoundData.writeFloat(leftSample);
				AS3SoundData.writeFloat(rightSample);
				if(sampleRate==22050){
					AS3SoundData.writeFloat(leftSample);
					AS3SoundData.writeFloat(rightSample);
				}
			}
			AS3SoundData.position=0;
		}
		
		public function writeSampleData(event:SampleDataEvent):void{
			var startPos:int=event.data.length;
			var toWrite:uint=AS3SoundData.bytesAvailable;
			if(!toWrite){
				AS3SoundData.position=0;
				return;
			}
			event.data.writeBytes(AS3SoundData,AS3SoundData.position,Math.min(toWrite,65536));
			AS3SoundData.position+=Math.min(toWrite,65536);
			for (var i:int = (event.data.length-startPos)/8; i < 8192; i++) 
			{ 
				event.data.writeFloat(0); 
				event.data.writeFloat(0); 
			}
		}
	}
}